package cn.tpshion.shop.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.tpshion.shop.common.BaseConstant;
import cn.tpshion.shop.domain.dto.TaskTakeDTO;
import cn.tpshion.shop.domain.entity.Task;
import cn.tpshion.shop.domain.entity.UserTask;
import cn.tpshion.shop.domain.vo.TaskVO;
import cn.tpshion.shop.domain.vo.support.TaskItem;
import cn.tpshion.shop.mapper.TaskMapper;
import cn.tpshion.shop.mapper.UserTaskMapper;
import cn.tpshion.shop.service.TaskService;
import cn.tpshion.shop.util.AssertUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Service
public class TaskServiceImpl implements TaskService {

    @Resource
    private TaskMapper taskMapper;

    @Resource
    private UserTaskMapper userTaskMapper;

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public TaskVO info() {
        TaskVO result = new TaskVO();

        List<Task> taskList = getTaskList();

        if (StpUtil.isLogin()) {
            long uid = StpUtil.getLoginIdAsLong();
            Integer userScore = getUserScore(uid);
            result.setScore(userScore);

            String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String key = BaseConstant.TASK_KEY + date;
            HashOperations<String, String, String> hash = redisTemplate.opsForHash();

            // 查询用户任务是否已完成
            List<TaskItem> list = taskList.stream().map(i -> {
                TaskItem item = new TaskItem();
                BeanUtils.copyProperties(i, item);

                if ("register".equals(i.getType())) {
                    String value = hash.get(BaseConstant.TASK_REGISTER_KEY, String.valueOf(uid));
                    item.setTake(StringUtils.isBlank(value) ? -1 : Integer.parseInt(value));
                } else {
                    String userKey = i.getType() + "-" + uid;
                    String value = hash.get(key, userKey);
                    item.setTake(StringUtils.isBlank(value) ? -1 : Integer.parseInt(value));
                }
                return item;
            }).toList();
            result.setList(list);
        } else {
            List<TaskItem> list = taskList.stream().map(i -> {
                TaskItem item = new TaskItem();
                BeanUtils.copyProperties(i, item);
                item.setTake(-1);
                return item;
            }).toList();
            result.setList(list);
            result.setScore(0);
        }
        return result;
    }

    @Override
    public void success(TaskTakeDTO dto) {
        long uid = StpUtil.getLoginIdAsLong();
        // 查询任务
        Task task = getTask(dto.getType());
        AssertUtil.isNull(task, "任务不存在");

        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        if ("register".equals(task.getType())) {
            hash.putIfAbsent(BaseConstant.TASK_REGISTER_KEY, String.valueOf(uid), "0");
        } else {
            String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String key = BaseConstant.TASK_KEY + date;
            String userKey = task.getType() + "-" + uid;
            hash.putIfAbsent(key, userKey, "0");

            Long expire = redisTemplate.getExpire(key);
            if (expire <= 0) {
                redisTemplate.expire(key, 2, TimeUnit.DAYS);
            }
        }
    }

    @Override
    public void take(TaskTakeDTO dto) {
        long uid = StpUtil.getLoginIdAsLong();

        // 查询任务
        Task task = getTask(dto.getType());
        AssertUtil.isNull(task, "任务不存在");

        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        if ("register".equals(task.getType())) {
            AssertUtil.isTrue(!hash.hasKey(BaseConstant.TASK_REGISTER_KEY, String.valueOf(uid)), "任务未完成");

            String value = hash.get(BaseConstant.TASK_REGISTER_KEY, String.valueOf(uid));
            AssertUtil.isTrue("1".equals(value), "任务已领取");

            hash.put(BaseConstant.TASK_REGISTER_KEY, String.valueOf(uid), "1");
        } else {
            String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String key = BaseConstant.TASK_KEY + date;
            String userKey = task.getType() + "-" + uid;
            AssertUtil.isTrue(!hash.hasKey(key, userKey), "任务未完成");

            String value = hash.get(key, userKey);
            AssertUtil.isTrue("1".equals(value), "任务已领取");

            hash.put(key, userKey, "1");
        }

        userTaskMapper.addScore(uid, task.getScore());
    }

    private Integer getUserScore(long uid) {
        LambdaQueryWrapper<UserTask> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserTask::getUid, uid);
        UserTask userTask = userTaskMapper.selectOne(queryWrapper);
        return Objects.isNull(userTask) ? 0 : userTask.getScore();
    }

    private List<Task> getTaskList() {
        LambdaQueryWrapper<Task> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Task::getStatus, 1);
        List<Task> tasks = taskMapper.selectList(queryWrapper);
        return ObjectUtils.isEmpty(tasks) ? Collections.emptyList() : tasks;
    }

    private Task getTask(String type) {
        LambdaQueryWrapper<Task> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Task::getType, type);
        return taskMapper.selectOne(queryWrapper);
    }
}
